//package com.hwbsite.hwbback.utils;
//
//import cn.hutool.core.convert.Convert;
//import cn.hutool.core.io.FileUtil;
//import com.baomidou.mybatisplus.core.toolkit.StringUtils;
//import lombok.extern.slf4j.Slf4j;
//import org.bytedeco.ffmpeg.avcodec.AVPacket;
//import org.bytedeco.ffmpeg.global.avcodec;
//import org.bytedeco.ffmpeg.global.avutil;
//import org.bytedeco.javacv.FFmpegFrameGrabber;
//import org.bytedeco.javacv.FFmpegFrameRecorder;
//import org.bytedeco.javacv.FFmpegLogCallback;
//import org.bytedeco.javacv.FrameRecorder;
//import org.springframework.stereotype.Component;
//
//import java.io.BufferedWriter;
//import java.io.File;
//import java.io.FileWriter;
//import java.io.IOException;
//import java.net.URL;
//import java.security.SecureRandom;
//import java.util.UUID;
//
//@Slf4j
//@Component
//public class FfmpegUtil {
//    public static String mp4ToM3u8(String filePathName, String toFilePath) throws Exception {
//
//        avutil.av_log_set_level(avutil.AV_LOG_INFO);
//        FFmpegLogCallback.set();
//
//        boolean isStart = true;// 该变量建议设置为全局控制变量，用于控制录制结束
//        //加载文件
//        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(filePathName);
//        //grabber.setAudioChannels(1);
//        grabber.start();
//        String fileName = UUID.randomUUID().toString().replaceAll("-", "");
//        File tempFile3 = new File(toFilePath, fileName + ".m3u8");
//
//        String prefixName = toFilePath + File.separator + fileName;
//        //生成加密key
//        String secureFileName = prefixName + ".key";
//        byte[] secureRandom = getSecureRandom();
//        FileUtil.writeBytes(secureRandom,secureFileName);
//
//        String toHex = Convert.toHex(secureRandom);
//        String keyInfoPath = toFilePath + File.separator +"key.keyinfo";
//        //写入加密文件
//        writeKeyInfo(keyInfoPath,fileName + ".key",secureFileName,toHex);
//
//        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(tempFile3, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
//        //格式方式
//        recorder.setFormat("hls");
//        //关于hls_wrap的说明，hls_wrap表示重复覆盖之前ts切片，这是一个过时配置，ffmpeg官方推荐使用hls_list_size 和hls_flags delete_segments代替hls_wrap
//        //设置单个ts切片的时间长度（以秒为单位）。默认值为2秒
//        recorder.setOption("hls_time", "10");
//        //不根据gop间隔进行切片,强制使用hls_time时间进行切割ts分片
//        recorder.setOption("hls_flags", "split_by_time");
//
//        //设置播放列表条目的最大数量。如果设置为0，则列表文件将包含所有片段，默认值为5
//        // 当切片的时间不受控制时，切片数量太小，就会有卡顿的现象
//        recorder.setOption("hls_list_size", "0");
//        //自动删除切片，如果切片数量大于hls_list_size的数量，则会开始自动删除之前的ts切片，只保留hls_list_size个数量的切片
//        recorder.setOption("hls_flags", "delete_segments");
//        //ts切片自动删除阈值，默认值为1，表示早于hls_list_size+1的切片将被删除
//        recorder.setOption("hls_delete_threshold", "1");
//        /*hls的切片类型：
//         * 'mpegts'：以MPEG-2传输流格式输出ts切片文件，可以与所有HLS版本兼容。
//         * 'fmp4':以Fragmented MP4(简称：fmp4)格式输出切片文件，类似于MPEG-DASH，fmp4文件可用于HLS version 7和更高版本。
//         */
//        recorder.setOption("hls_segment_type", "mpegts");
//        //指定ts切片生成名称规则，按数字序号生成切片,例如'file%03d.ts'，就会生成file000.ts，file001.ts，file002.ts等切片文件
//        //recorder.setOption("hls_segment_filename", toFilePath + "-%03d.ts");
//        recorder.setOption("hls_segment_filename", toFilePath + File.separator + fileName + "-%5d.ts");
//        //加密
//        recorder.setOption("hls_key_info_file", keyInfoPath);
//        // 设置第一个切片的编号
////        recorder.setOption("start_number", String.valueOf(tsCont));
////        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
//
//        // 转码
//        log.info("{} | 启动Hls转码录制器……", toFilePath);
//        //      设置零延迟
//        //recorder.setVideoOption("tune", "zerolatency");
//        recorder.setVideoOption("tune", "fastdecode");
//        // 快速
//        recorder.setVideoOption("preset", "ultrafast");
////        recorder.setVideoOption("crf", "26");
//        recorder.setVideoOption("threads", "12");
//        recorder.setVideoOption("vsync", "2");
//        recorder.setFrameRate(grabber.getFrameRate());// 设置帧率
////        recorder.setGopSize(25);// 设置gop,与帧率相同，相当于间隔1秒chan's一个关键帧
////		recorder.setVideoBitrate(100 * 1000);// 码率500kb/s
//        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
////        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
//        recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
//
//
//        //如果想截取规定时间段视频
////        recorder.start();
////        Frame frame;
////        while ((frame = grabber.grabImage()) != null) {
////            try {
////                recorder.record(frame);
////            } catch (FrameRecorder.Exception e) {
////                log.error("转码异常：{}", e);
////            }
////        }
//        recorder.start(grabber.getFormatContext());
//        AVPacket packet;
//        while ((packet = grabber.grabPacket()) != null) {
//            try {
//                recorder.recordPacket(packet);
//            } catch (FrameRecorder.Exception e) {
//                log.error("转码异常：{}", e);
//            }
//        }
//        recorder.setTimestamp(grabber.getTimestamp());
//        recorder.stop();
//        recorder.release();
//        grabber.stop();
//        grabber.release();
//
//        File dest = new File(filePathName);
//        if (dest.isFile() && dest.exists()) {
//            dest.delete();
//            log.warn("临时文件 {}已删除", dest.getName());
//        }
//        log.info("转码m3u8：{}", tempFile3.getAbsolutePath());
//        return tempFile3.getAbsolutePath();
//    }
//
//    public static byte[] getSecureRandom(){
//        byte[] bytes = new byte[16];
//        new SecureRandom().nextBytes(bytes);
//        return bytes;
//    }
//
//    public static void writeKeyInfo(String keyInfoPath,String decrypt,String encrypt,String IV) throws IOException {
//        try (BufferedWriter writer = new BufferedWriter(new FileWriter(keyInfoPath));){
//            writer.write(decrypt);
//            writer.newLine();
//            writer.write(encrypt);
//            writer.newLine();
//            if(StringUtils.isNotBlank(IV)){
//                writer.write(IV);
//            }
//            writer.flush();
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }
//    }
//}
